/*
 * @Author: 吴世扬 18368095041@163.com
 * @Date: 2024-05-27 16:07:47
 * @LastEditors: 吴世扬 18368095041@163.com
 * @LastEditTime: 2024-08-22 18:01:05
 * @FilePath: /vue3-uniapp/src/plugins/httpInterceptor.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import { un, requestAdapter } from '@uni-helper/uni-network';
import { Subject } from 'rxjs';

import { isObject, isArray, isHttpData } from '@/utils/assert';
import { useUserStore } from '@/store';
import { useNotifySubject } from '@/service/app/useNotifySubject';
import { mockAdapter } from '@/mock/index';

const fitlerUtf8mb4 = (str: string) => {
    let newStr = '';
    for (const c of str) {
        const char = c.codePointAt(0);
        if (char && char <= 65535) {
            newStr += char;
        }
    }
    return newStr;
};

const filterObject = (data: unknown) => {
    if (isObject(data)) {
        const keys = Object.keys(data);
        keys.forEach((key) => {
            const value = data[key];
            const valueType = Object.prototype.toString.call(value);
            if (valueType === '[object Object]') {
                filterObject(value);
            } else if (isArray(value)) {
                value.forEach((item) => {
                    filterObject(item);
                });
            } else if (typeof value === 'string') {
                data[key] = fitlerUtf8mb4(value);
            }
        });
    } else if (isArray(data)) {
        data.forEach((item) => {
            filterObject(item);
        });
    }
};

export const setupHttpInterceptor: SetupFunc = () => {
    const userStore = useUserStore();
    const { token } = storeToRefs(userStore);
    const { danger } = useNotifySubject();

    un.defaults.baseUrl = import.meta.env.VITE_API_BASEURL;
    un.defaults.headers = {
        'Content-Type': 'application/json'
    };
    un.defaults.timeout = 20000;

    un.defaults.adapter = (config) => {
        if (token.value === 'mock') {
            const response = mockAdapter(config.url, config.data);
            if (response === undefined) {
                return Promise.resolve({
                    status: 404,
                    data: {
                        code: 404,
                        msg: `mock请求${config.url}不存在`,
                        data: {}
                    }
                });
                // return Promise.reject(`mock请求${config.url}不存在`);
            }
            response.then((res) => {
                console.log(`mock请求`, config, res);
            });
            return response;
        }
        return requestAdapter(config);
    };

    un.interceptors.request.use((config) => {
        if (token.value) {
            config.headers = {
                ...(config.headers || {}),
                token: token.value
            };
        }
        // 过滤4字节字符
        // if (config.data) {
        //     filterObject(config.data);
        // } else if (config.params) {
        //     filterObject(config.params);
        // }
        return config;
    });

    const unAuthSubject = new Subject<string>();
    const unAuth$ = unAuthSubject.pipe(throttleTime(3000));
    unAuth$.subscribe({
        next: (msg) => {
            userStore.logout();
            userStore.createBackRouteOptionAndGoLogin();
            danger({
                msg: msg || '请先登录哦'
            });
        }
    });

    un.interceptors.response.use(
        (res) => {
            const { data, config } = res;
            if (isHttpData(data)) {
                if (data.code === -1 || data.code === 401) {
                    unAuthSubject.next(data.msg);
                    return Promise.reject(res);
                } else if (data.code !== 0) {
                    if (data.code) {
                        console.log(
                            `error[${config?.url || '未知请求'}]: ${data.msg}`
                        );
                        danger({
                            msg: data.msg
                        });
                        return Promise.reject(res);
                    } else {
                        return Promise.reject(res);
                    }
                }
                return res;
            } else {
                return res;
            }
        },
        async (res) => {
            // 先不考虑小程序并发请求的一些问题，这个是官方的bug，出现这个问题就参考指挥中心项目的处理方法
            // const { config } = res;
            // if (config) {
            //     if (
            //         [res.errMsg, res.config.errMsg].includes(
            //             'request:fail timeout'
            //         ) ||
            //         [res.errMsg, res.config.errMsg].includes(
            //             'request:fail fail:time out'
            //         ) ||
            //         res.errno === 5
            //     ) {
            //         console.log(
            //             `request:fail timeout start~~~~~~~~~~~~~~~~~~~~~~~~~~~`
            //         );
            //         console.log(res);
            //         console.log(
            //             `request:fail timeout end~~~~~~~~~~~~~~~~~~~~~~~~~~~`
            //         );
            //         const resData = await un.request(config);
            //         return Promise.resolve(resData);
            //     } else {
            //         handleWaitingList(config);
            //     }
            // }
            danger({
                msg: '网络信号差，请稍后再试'
            });
            return Promise.reject(res);
        }
    );
};
